package com.ly.heart.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.extra.spring.SpringUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ly.activiti.service.IProcessDefinitionService;
import com.ly.common.core.domain.BaseVo;
import com.ly.common.core.domain.ActCurrentTaskVo;
import com.ly.common.core.domain.AjaxResult;
import com.ly.common.core.domain.entity.SysMenu;
import com.ly.common.core.domain.entity.SysRole;
import com.ly.common.core.domain.entity.SysUser;
import com.ly.common.utils.DateUtils;
import com.ly.common.utils.SecurityUtils;
import com.ly.common.utils.StringUtils;
import com.ly.common.utils.erp.ReturnPage;
import com.ly.common.utils.erp.SnowflakeIdWorker;
import com.ly.heart.activiti.pojo.ProcessModel;
import com.ly.heart.activiti.util.BpmnUtil;
import com.ly.heart.domain.*;
import com.ly.heart.domain.dto.*;
import com.ly.heart.domain.vo.*;
import com.ly.heart.mapper.ActModelMapper;
import com.ly.heart.service.*;
import com.ly.system.domain.SysUserRole;
import com.ly.system.service.ISysMenuService;
import com.ly.system.service.ISysRoleService;
import com.ly.system.service.ISysUserRoleService;
import com.ly.system.service.ISysUserService;
import org.activiti.api.process.model.builders.ProcessPayloadBuilder;
import org.activiti.api.process.runtime.ProcessRuntime;
import org.activiti.bpmn.converter.BpmnXMLConverter;
import org.activiti.bpmn.model.BpmnModel;
import org.activiti.bpmn.model.FlowNode;
import org.activiti.bpmn.model.SequenceFlow;
import org.activiti.engine.HistoryService;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.RuntimeService;
import org.activiti.engine.TaskService;
import org.activiti.engine.history.*;
import org.activiti.engine.impl.identity.Authentication;
import org.activiti.engine.repository.Deployment;
import org.activiti.engine.repository.ProcessDefinition;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.task.IdentityLink;
import org.activiti.engine.task.IdentityLinkType;
import org.activiti.engine.task.Task;
import org.activiti.engine.task.TaskQuery;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.io.IOException;
import java.util.*;
import java.util.stream.Collectors;

@Service
public class ActModelServiceImpl extends ServiceImpl<ActModelMapper, ActModelEntity> implements IActModelService {

    @Resource
    private ActModelMapper actModelMapper;
    @Resource
    private IActGroupService actGroupService;
    @Resource
    private IActMenuService actMenuService;
    @Resource
    private ISysMenuService sysMenuService;
    @Resource
    private ISysUserRoleService userRoleService;
    @Resource
    private ISysUserService userService;
    @Resource
    private ISysRoleService roleService;
    @Resource
    private IActTaskCommentService taskCommentService;
    @Resource
    private IActModelBusinessService modelBusinessService;
    @Resource
    private IProcessDefinitionService iProcessDefinitionService;
    @Resource
    private RepositoryService repositoryService;
    @Resource
    private TaskService taskService;
    @Resource
    private HistoryService historyService;
    @Resource
    private RuntimeService runtimeService;
    @Resource
    private ProcessRuntime processRuntime;



    private LambdaQueryWrapper<ActModelEntity> baseQuery(ActModelQueryDto queryDto){
        LambdaQueryWrapper<ActModelEntity> query = new LambdaQueryWrapper<>();
        if(StringUtils.isNotEmpty(queryDto.getCode())){
            query.like(ActModelEntity::getCode,queryDto.getCode());
        }
        if(StringUtils.isNotEmpty(queryDto.getName())){
            query.like(ActModelEntity::getName,queryDto.getName());
        }
        if(StringUtils.isNotEmpty(queryDto.getGroupId())){
            query.eq(ActModelEntity::getGroupId,queryDto.getGroupId());
        }
        if(StringUtils.isNotEmpty(queryDto.getGroupName())){
            List<ActGroupEntity> groupList = actGroupService.list(new LambdaQueryWrapper<ActGroupEntity>().like(ActGroupEntity::getGroupName, queryDto.getGroupName()));
            List<String> groupIdList = groupList.stream().map(ActGroupEntity::getId).collect(Collectors.toList());
            if(CollectionUtil.isNotEmpty(groupList)){
                query.in(ActModelEntity::getGroupId,groupIdList);
            }else{
                query.isNull(ActModelEntity::getGroupId);
            }
        }
        if(queryDto.getState() != null){
            query.eq(ActModelEntity::getState,queryDto.getState());
        }
        query.orderByDesc(ActModelEntity::getCreateTime);
        return query;
    }

    /**
     * 接收前端流程对象，转化为bpmn,通过activiti部署流程信息
     * 保存流程对象和activiti关联关系
     * @param processModel 流程信息
     * @return
     */
    @Override
    public AjaxResult deployActByNode(ProcessModel processModel) throws IOException {
        System.out.println("打印参数信息-----------------");
        //转为bpmnModel文件
        BpmnModel bpmnModel = BpmnUtil.toBpmnModel(processModel);
        //流程编码
        String modelCode = processModel.getProcess().getId().concat("_process.bpmn");
        Deployment deployment = repositoryService.createDeployment().name(processModel.getName()).addBpmnModel(modelCode, bpmnModel).deploy();

        // 获取流程引擎对象
//        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
//        DeploymentBuilder deploymentBuilder = processEngine.getRepositoryService().createDeployment();
//        byte[] bytes = convertBpmnModelToBytes(bpmnModel);
//        deploymentBuilder.addBytes("process.bpmn", bytes);
//        Deployment deployment = deploymentBuilder.deploy();

        if(Objects.nonNull(deployment) && deployment.getId() != null){
            //获取流程定义key,使用部署对象的ID查询
            ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery()
                    .deploymentId(deployment.getId())
                    .singleResult();
            ActModelEntity saveActModel = new ActModelEntity().setId(SnowflakeIdWorker.getInstance().nextStringId()).setCode(processModel.getCode()).setName(processModel.getName()).setVersion(processDefinition.getVersion()).setSort(processModel.getSort()).setGroupId(processModel.getGroupId())
                .setRemark(processModel.getRemark()).setModelData(processModel.getModelData()).setFormData(processModel.getFormData())
                .setProcessDefId(processDefinition.getId()).setDeployId(deployment.getId()).setState(1).setCreateTime(DateUtils.getNowDate());
            this.save(saveActModel);
            //插入流程模型与菜单关联信息
            if(Objects.nonNull(processModel.getMenuId())){
                ActMenuEntity actMenu = actMenuService.getOne(new QueryWrapper<ActMenuEntity>().eq("menu_id", processModel.getMenuId()));
                if(Objects.isNull(actMenu)){
                    ActMenuEntity saveActMenu = new ActMenuEntity().setId(SnowflakeIdWorker.getInstance().nextStringId()).setMenuId(processModel.getMenuId()).setModelId(saveActModel.getId()).setUserId(SecurityUtils.getLoginUser().getUser().getUserId()).setCreateTime(DateUtils.getNowDate());
                    actMenuService.save(saveActMenu);
                }else {
                    ActMenuEntity updateActMenu = new ActMenuEntity().setId(actMenu.getId()).setMenuId(processModel.getMenuId()).setModelId(saveActModel.getId()).setChangeTime(DateUtils.getNowDate());
                    actMenuService.updateById(updateActMenu);
                }
            }
            return AjaxResult.success("操作成功！");
        }
        return AjaxResult.error("操作失败！");
    }

    public static byte[] convertBpmnModelToBytes(BpmnModel bpmnModel) throws IOException {
        BpmnXMLConverter bpmnXMLConverter = new BpmnXMLConverter();
        byte[] bpmnBytes = bpmnXMLConverter.convertToXML(bpmnModel, "UTF-8");
        return bpmnBytes;
    }

    @Override
    public AjaxResult getActModelPageList(ActModelQueryDto queryDto){
        LambdaQueryWrapper<ActModelEntity> query = this.baseQuery(queryDto);
        List<ActModelEntity> actModelList = this.list(query);
        List<ActModelVo> modelVos = new ArrayList<>();
        if(CollectionUtil.isNotEmpty(actModelList)){
            modelVos = actModelList.stream().map(a -> {
                ActModelVo modelVo = new ActModelVo().setId(a.getId()).setCode(a.getCode()).setName(a.getName()).setVersion(a.getVersion()).setSort(a.getSort())
                    .setRemark(a.getRemark()).setModelData(a.getModelData()).setFormData(a.getFormData()).setProcessDefId(a.getProcessDefId()).setDeployId(a.getDeployId()).setState(a.getState()).setStateName(a.getState()).setCreateTime(a.getCreateTime());
                ActGroupEntity actGroupEntity = actGroupService.selectActGroupById(a.getGroupId());
                Optional.ofNullable(actGroupEntity).ifPresent(g -> {
                    modelVo.setGroupId(g.getId()).setGroupName(g.getGroupName());
                });
                return modelVo;
            }).collect(Collectors.toList());
        }
        Page<ActModelVo> page = new Page<>(queryDto.getPage(), queryDto.getLimit());
        return AjaxResult.success(ReturnPage.getReturnPage(page,modelVos));
    }


    @Override
    public AjaxResult getActModelList(ActModelQueryDto queryDto){
        LambdaQueryWrapper<ActModelEntity> query = this.baseQuery(queryDto);
        List<ActModelEntity> actModelList = this.list(query);
        List<ActModelVo> modelVos = new ArrayList<>();
        if(CollectionUtil.isNotEmpty(actModelList)){
            modelVos = actModelList.stream().map(a -> {
                ActModelVo modelVo = new ActModelVo().setId(a.getId()).setCode(a.getCode()).setName(a.getName()).setVersion(a.getVersion()).setSort(a.getSort())
                        .setRemark(a.getRemark()).setModelData(a.getModelData()).setFormData(a.getFormData()).setProcessDefId(a.getProcessDefId()).setDeployId(a.getDeployId()).setState(a.getState()).setStateName(a.getState()).setCreateTime(a.getCreateTime());
                ActGroupEntity actGroup = actGroupService.getById(a.getGroupId());
                Optional.ofNullable(actGroup).ifPresent(group -> {
                    modelVo.setGroupId(group.getId()).setGroupName(group.getGroupName());
                });
                return modelVo;
            }).collect(Collectors.toList());
        }
        return AjaxResult.success(modelVos);
    }

    @Override
    public AjaxResult suspendOrActiveApply(SuspendOrActiveDto activeDto){
        ActModelEntity actModel = this.getById(activeDto.getId());
        if(activeDto.getState().equals(actModel.getState())){
            return AjaxResult.error("重复操作！");
        }
        ActModelEntity updateState = new ActModelEntity().setId(activeDto.getId()).setState(activeDto.getState());
        boolean updated = this.updateById(updateState);
        if(updated){
            iProcessDefinitionService.suspendOrActiveApply(activeDto.getProcessDefId(),activeDto.getState());
        }
        return AjaxResult.success("操作成功！");
    }


    @Override
    public AjaxResult delActModelByDeployId(String id){
        ActModelEntity actModel = this.getById(id);
        repositoryService.deleteDeployment ( actModel.getDeployId(), false );
        boolean removedById = this.removeById(id);
        if(removedById){
            return AjaxResult.success("删除成功！");
        }else {
            return AjaxResult.error("删除失败！");
        }
    }


    @Override
    public AjaxResult getActModelByMenuId(String menuId){
        ActMenuEntity actMenu = actMenuService.getOne(new QueryWrapper<ActMenuEntity>().eq("menu_id", menuId));
        ActModelEntity actModel = this.getById(actMenu.getModelId());
        if(ObjectUtil.isAllNotEmpty(actMenu,actModel)){
            return AjaxResult.success(actModel);
        }
        return AjaxResult.success(new ActModelEntity());
    }

    @Override
    public AjaxResult getMenuOption(){
        List<SysMenu> sysMenus = sysMenuService.list(new QueryWrapper<SysMenu>().eq("related_model", Boolean.TRUE).eq("hide_route",1));
        List<ActMenuVo> data = new ArrayList<>();
        if(CollectionUtil.isNotEmpty(sysMenus)){
            data = sysMenus.stream().map(menu -> {
                ActMenuVo menuVo = new ActMenuVo().setMenuId(menu.getMenuId()).setMenuName(menu.getMenuName());
                return menuVo;
            }).collect(Collectors.toList());
        }
        return AjaxResult.success(data);
    }


    @Override
    public AjaxResult getTasksByRoleId(ActTaskQueryDto queryDto){
        String userId = SecurityUtils.getLoginUser().getUser().getUserId();
        if(Objects.isNull(userId)){
            return AjaxResult.error("账户信息异常！");
        }
        List<SysUserRole> userRoleList = userRoleService.list(new QueryWrapper<SysUserRole>().eq("user_id", userId));
        if(CollectionUtil.isEmpty(userRoleList)){
            return AjaxResult.error("用户角色信息异常！");
        }
        List<String> roleIdList = userRoleList.stream().distinct().map(SysUserRole::getRoleId).collect(Collectors.toList());
        List<ActTaskVo> tasks = new ArrayList<>();
        TaskQuery taskQuery = taskService.createTaskQuery();
        taskQuery.taskCandidateGroupIn(roleIdList);
        if(Objects.nonNull(queryDto.getProcessName())){
            taskQuery.processDefinitionNameLike("%"+queryDto.getProcessName()+"%");
        }
        if(Objects.nonNull(queryDto.getTaskName())){
            taskQuery.taskNameLike("%"+queryDto.getTaskName()+"%");
        }
        taskQuery.orderByTaskCreateTime().desc();
        List<Task> taskList = taskQuery.list();
        if(CollectionUtil.isNotEmpty(taskList)){
            tasks = taskList.stream().map(task -> {
                ActTaskVo taskVo = new ActTaskVo().setTaskId(task.getId()).setTaskName(task.getName());
                ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceId(task.getProcessInstanceId()).singleResult();
                taskVo.setInstanceId(task.getProcessInstanceId()).setInstanceName(processInstance.getName()).setDefinitionKey(processInstance.getProcessDefinitionKey()).setBusinessKey(processInstance.getBusinessKey()).setCreateTime(task.getCreateTime());
                String taskStatus = task.getExecutionId() != null ? "进行中" : "已完成";
                taskVo.setStatus(taskStatus);
                ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().processDefinitionId(processInstance.getProcessDefinitionId())
                        .singleResult();
                taskVo.setProcessName(processDefinition.getName());
                //获取发起人
                if(Objects.nonNull(processInstance.getStartUserId())){
                    taskVo.setStartUserId(processInstance.getStartUserId());
                    SysUser sysUser = userService.getById(processInstance.getStartUserId());
                    Optional.ofNullable(sysUser).ifPresent(user -> {
                        taskVo.setStartUserName(user.getUserName());
                    });
                }
                ActModelEntity actModelEntity = this.getOne(new QueryWrapper<ActModelEntity>().eq("process_def_id", processDefinition.getId()));
                Optional.ofNullable(actModelEntity).ifPresent(actModel -> {
                    taskVo.setModelData(actModel.getModelData()).setFormData(actModel.getFormData());
                    ActMenuEntity actMenuEntity = actMenuService.getOne(new QueryWrapper<ActMenuEntity>().eq("model_id", actModel.getId()));
                    Optional.ofNullable(actMenuEntity).ifPresent(actMenu -> {
                        taskVo.setMenuId(actMenu.getMenuId());
                    });
                });
                return taskVo;
            }).collect(Collectors.toList());
        }
        Page<ActTaskVo> page = new Page<>(queryDto.getPage(),queryDto.getLimit());
        return AjaxResult.success(ReturnPage.getReturnPage(page,tasks));
    }

    @Override
    public AjaxResult getBusinessDataByInstanceId(String instanceId){
        IActModelBusinessService modelBusinessService = SpringUtil.getBean(IActModelBusinessService.class);
        String businessDataByBusinessType = modelBusinessService.getBusinessDataByBusinessType(instanceId);
        return AjaxResult.success(businessDataByBusinessType);
    }



    @Override
    public AjaxResult getCompletedTasksByRoleId(ActTaskQueryDto queryDto) {
        String userId = SecurityUtils.getLoginUser().getUser().getUserId();
        if(Objects.isNull(userId)){
            return AjaxResult.error("账户信息异常！");
        }
        List<SysUserRole> userRoleList = userRoleService.list(new QueryWrapper<SysUserRole>().eq("user_id", userId));
        if(CollectionUtil.isEmpty(userRoleList)){
            return AjaxResult.error("用户角色信息异常！");
        }
        List<String> roleIdList = userRoleList.stream().distinct().map(SysUserRole::getRoleId).collect(Collectors.toList());
 //       List<HistoricTaskInstance> historicTasks = historyService.createHistoricTaskInstanceQuery().taskCandidateGroupIn(roleIdList).finished().list();
        HistoricTaskInstanceQuery historicTaskQuery = historyService.createHistoricTaskInstanceQuery();
        historicTaskQuery.taskCandidateGroupIn(roleIdList).finished();
        if(Objects.nonNull(queryDto.getProcessName())){
            historicTaskQuery.processDefinitionNameLike("%"+queryDto.getProcessName()+"%");
        }
        if(Objects.nonNull(queryDto.getTaskName())){
            historicTaskQuery.taskNameLike("%"+queryDto.getTaskName()+"%");
        }
        historicTaskQuery.orderByTaskCreateTime().desc();
        List<HistoricTaskInstance> historicTasks = historicTaskQuery.list();
        List<ActTaskVo> tasks = new ArrayList<>();
        if(CollectionUtil.isNotEmpty(historicTasks)){
            tasks = historicTasks.stream().map(historyTask -> {
                ActTaskVo taskVo = new ActTaskVo().setTaskId(historyTask.getId()).setTaskName(historyTask.getName());
                HistoricProcessInstance processInstance = historyService.createHistoricProcessInstanceQuery()
                    .processInstanceId(historyTask.getProcessInstanceId()).singleResult();
                if(Objects.nonNull(processInstance)){
                    taskVo.setInstanceId(processInstance.getId()).setInstanceName(processInstance.getName()).setDefinitionKey(processInstance.getProcessDefinitionKey()).setBusinessKey(processInstance.getBusinessKey()).setCreateTime(historyTask.getCreateTime());
                    ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery()
                        .processDefinitionId(processInstance.getProcessDefinitionId()).singleResult();
                    if (processDefinition != null) {
                        taskVo.setProcessName(processDefinition.getName());
                    }
                }
                List<ActTaskCommentVo> commentData = new ArrayList<>();
                List<ActTaskCommentEntity> commentList = taskCommentService.list(new QueryWrapper<ActTaskCommentEntity>().eq("task_id", historyTask.getId()));
                if(!CollectionUtils.isEmpty(commentList)){
                    commentList.forEach(comments -> {
                        ActTaskCommentVo commentVo = new ActTaskCommentVo().setTaskId(historyTask.getId());
                        commentVo.setTaskName(historyTask.getName()).setAssignee(comments.getAssignee()).setComments(comments.getComments()).setCommentsName(comments.getComments()).setRemark(comments.getRemark()).setCreateTime(comments.getCreateTime());
                        SysUser sysUser = userService.getById(comments.getAssignee());
                        Optional.ofNullable(sysUser).ifPresent(user -> {
                            commentVo.setAssigneeName(user.getUserName());
                        });
                        commentData.add(commentVo);
                    });
                    taskVo.setComments(commentData);
                    taskVo.setStatus("已完成");
                }else{
                    taskVo.setStatus("进行中");
                }
                //获取发起人
                if(Objects.nonNull(processInstance.getStartUserId())){
                    taskVo.setStartUserId(processInstance.getStartUserId());
                    SysUser sysUser = userService.getById(processInstance.getStartUserId());
                    Optional.ofNullable(sysUser).ifPresent(user -> {
                        taskVo.setStartUserName(user.getUserName());
                    });
                    ActModelEntity actModelEntity = this.getOne(new QueryWrapper<ActModelEntity>().eq("process_def_id", processInstance.getProcessDefinitionId()));
                    Optional.ofNullable(actModelEntity).ifPresent(actModel -> {
                        taskVo.setModelData(actModel.getModelData()).setFormData(actModel.getFormData());
                        ActMenuEntity actMenuEntity = actMenuService.getOne(new QueryWrapper<ActMenuEntity>().eq("model_id", actModel.getId()));
                        Optional.ofNullable(actMenuEntity).ifPresent(actMenu -> {
                            taskVo.setMenuId(actMenu.getMenuId());
                        });
                    });
                }
                return taskVo;
            }).collect(Collectors.toList());
        }
        Page<ActTaskVo> page = new Page<>(queryDto.getPage(),queryDto.getLimit());
        return AjaxResult.success(ReturnPage.getReturnPage(page,tasks));
    }

    @Override
    public AjaxResult getTaskByUserId(BaseVo baseVo){
        String userId = SecurityUtils.getLoginUser().getUser().getUserId();
        if(Objects.isNull(userId)){
            return AjaxResult.error("账户信息异常！");
        }
        List<ActMyInstanceVo> data = new ArrayList<>();
        // 查询已完成的历史流程实例
        List<HistoricProcessInstance> historicProcessInstances = historyService.createHistoricProcessInstanceQuery().startedBy(userId).list();
        // 处理已完成的历史流程实例
        if (!CollectionUtils.isEmpty(historicProcessInstances)) {
            data.addAll(historicProcessInstances.stream().map(
               p ->{
                   ActMyInstanceVo instanceVo = new ActMyInstanceVo().setInstanceId(p.getId()).setInstanceName(p.getName()).setCreateTime(p.getStartTime()).setDefinitionKey(p.getProcessDefinitionKey())
                   .setBusinessKey(p.getBusinessKey()).setStartTime(p.getStartTime()).setEndTime(p.getEndTime()).setStatus("已完成");
                   ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().processDefinitionId(p.getProcessDefinitionId()).singleResult();
                   if(Objects.nonNull(processDefinition)){
                       instanceVo.setProcessName(processDefinition.getName());
                       ActModelEntity actModelEntity = this.getOne(new QueryWrapper<ActModelEntity>().eq("process_def_id", processDefinition.getId()));
                       Optional.ofNullable(actModelEntity).ifPresent(actModel -> {
                           instanceVo.setModelData(actModel.getModelData()).setFormData(actModel.getFormData());
                           ActMenuEntity actMenuEntity = actMenuService.getOne(new QueryWrapper<ActMenuEntity>().eq("model_id", actModel.getId()));
                           Optional.ofNullable(actMenuEntity).ifPresent(actMenu -> {
                               instanceVo.setMenuId(actMenu.getMenuId());
                           });
                       });
                   }
                   return instanceVo;
               }).collect(Collectors.toList())
            );
        }
        // 查询正在进行中的流程实例
        List<ProcessInstance> runningProcessInstances = runtimeService.createProcessInstanceQuery().startedBy(userId).list();
        // 处理正在进行中的流程实例
        if (!CollectionUtils.isEmpty(runningProcessInstances)) {
            data.addAll(
                runningProcessInstances.stream().map(p -> {
                    ActMyInstanceVo instanceVo = new ActMyInstanceVo().setInstanceId(p.getId()).setInstanceName(p.getName()).setCreateTime(p.getStartTime()).setDefinitionKey(p.getProcessDefinitionKey()).setBusinessKey(p.getBusinessKey()).setStartTime(p.getStartTime()).setStatus("进行中");
                    ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().processDefinitionId(p.getProcessDefinitionId()).singleResult();
                    if(Objects.nonNull(processDefinition)){
                        instanceVo.setProcessName(processDefinition.getName());
                        ActModelEntity actModelEntity = this.getOne(new QueryWrapper<ActModelEntity>().eq("process_def_id", processDefinition.getId()));
                        Optional.ofNullable(actModelEntity).ifPresent(actModel -> {
                            instanceVo.setModelData(actModel.getModelData()).setFormData(actModel.getFormData());
                            ActMenuEntity actMenuEntity = actMenuService.getOne(new QueryWrapper<ActMenuEntity>().eq("model_id", actModel.getId()));
                            Optional.ofNullable(actMenuEntity).ifPresent(actMenu -> {
                                instanceVo.setMenuId(actMenu.getMenuId());
                            });
                        });
                    }
                    return instanceVo;
                 }).collect(Collectors.toList())
            );
        }
//        List<ActMyInstanceVo> filteredData = data.stream()
//                .filter(instance -> instance.getInstanceName() != null && instance.getInstanceName().contains(searchName))
//                .collect(Collectors.toList());
        data.sort(Comparator.comparing(ActMyInstanceVo::getCreateTime).reversed());
        Page<ActMyInstanceVo> page = new Page<>(baseVo.getPage(),baseVo.getLimit());
        return AjaxResult.success(ReturnPage.getReturnPage(page,data));
    }

    @Override
    public AjaxResult getTasksByInstanceId(String instanceId){
        List<ActTaskListDto> tasks = new ArrayList<>();
        // 查询正在进行中的任务
        List<Task> activeTasks = taskService.createTaskQuery().processInstanceId(instanceId).list();
        // 查询已完成的任务
        List<HistoricTaskInstance> completedTasks = historyService.createHistoricTaskInstanceQuery()
                .processInstanceId(instanceId)
                .finished()
                .list();
        for(Task activeTask : activeTasks){
            ActTaskListDto taskDto = new ActTaskListDto();
            taskDto.setTaskId(activeTask.getId());
            taskDto.setTaskName(activeTask.getName());
            tasks.add(taskDto);
        }
        for(HistoricTaskInstance historicTask : completedTasks){
            ActTaskListDto taskDto = new ActTaskListDto();
            taskDto.setTaskId(historicTask.getId());
            taskDto.setTaskName(historicTask.getName());
            tasks.add(taskDto);
        }
        return AjaxResult.success(tasks);
    }


    @Override
    public AjaxResult completeTaskByTaskId(ActTaskCompleteDto completeDto) {
        Task currentTask = taskService.createTaskQuery().taskId(completeDto.getTaskId()).singleResult();
        if (Objects.nonNull(currentTask)) {
            switch (completeDto.getAction()) {
                //通过
                case "0":
                    taskService.complete(currentTask.getId());
                    addTaskComment(currentTask,completeDto);
                    modelBusinessService.updateBusinessState(currentTask);
                    break;
                //拒绝
                case "1":
                    runtimeService.deleteProcessInstance(currentTask.getProcessInstanceId(), "审核拒绝");
//                    taskService.complete(currentTask.getId());
                    addTaskComment(currentTask,completeDto);
                    break;
                //退回
                case "2":
                    addTaskComment(currentTask,completeDto);
                    backProcessToLast(currentTask);
                    break;
            }
            return AjaxResult.success("操作成功！");
        }
        return AjaxResult.error("任务不存在！");
    }



    @Override
    public String startProcess(StartProcessDto startDto){
        Authentication.setAuthenticatedUserId(SecurityUtils.getLoginUser().getUser().getUserId());
        ActModelEntity actModel = this.getById(startDto.getModelId());
        org.activiti.api.process.model.ProcessInstance processInstance = processRuntime.start(ProcessPayloadBuilder.start()
            .withProcessDefinitionId(actModel.getProcessDefId()).withBusinessKey(startDto.getBusinessId()).withName(startDto.getBusinessName()).build());
        if(Objects.nonNull(startDto.getBusinessType())){
            ActModelBusinessEntity modelBusiness = new ActModelBusinessEntity().setId(SnowflakeIdWorker.getInstance().nextStringId())
                .setBusinessId(startDto.getBusinessId()).setBusinessType(startDto.getBusinessType()).setInstanceId(processInstance.getId()).setUserId(SecurityUtils.getLoginUser().getUser().getUserId()).setCreateTime(DateUtils.getNowDate());
            modelBusinessService.save(modelBusiness);
        }
        return processInstance.getId();
    }

    @Override
    public ActCurrentTaskVo getCurrentTaskByInstanceId(String instanceId){
        ActCurrentTaskVo currentTaskVo = new ActCurrentTaskVo();
        //获取当前活跃的任务
        List<Task> tasks = taskService.createTaskQuery().processInstanceId(instanceId).active().list();
        if (!tasks.isEmpty()) {
            Task currentTask = tasks.get(0);
            String taskId = currentTask.getId();
            String name = currentTask.getName();
            //根据当前任务id获取该任务的审批角色组
            List<String> groupIds = taskService.getIdentityLinksForTask(taskId).stream().filter(link -> link.getType().equals(IdentityLinkType.CANDIDATE)).map(link -> link.getGroupId()).collect(Collectors.toList());
            currentTaskVo.setInstanceId(instanceId).setTaskId(taskId).setTaskName(name).setGroupIds(groupIds);
            if(!CollectionUtils.isEmpty(groupIds)){
                Map<String,String> groupNames = new HashMap<>();
                groupIds.forEach(groupId -> {
                    SysRole sysRole = roleService.getById(groupId);
                    Optional.ofNullable(sysRole).ifPresent(role -> {
                        groupNames.put(groupId,role.getRoleName());
                    });
                });
                currentTaskVo.setGroupNames(groupNames);
            }
        }
        return currentTaskVo;
    }

    /**
     * 审核操作
     * @param currentTask
     * @param completeDto
     */
    public void addTaskComment(Task currentTask,ActTaskCompleteDto completeDto){
        ActTaskCommentEntity taskComment = new ActTaskCommentEntity().setId(SnowflakeIdWorker.getInstance().nextStringId()).setInstanceId(currentTask.getProcessInstanceId())
            .setTaskId(currentTask.getId()).setComments(completeDto.getAction()).setRemark(completeDto.getRemark()).setAssignee(SecurityUtils.getLoginUser().getUser().getUserId()).setCreateTime(DateUtils.getNowDate());
        taskCommentService.save(taskComment);
    }

    /**
     * todo 向下一审批组发送提醒消息
     * 发送消息
     * @param currentTask
     */
    public void sendMessageToNext(Task currentTask){
        String processDefinitionId = currentTask.getProcessDefinitionId();
        ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().processDefinitionId(processDefinitionId).singleResult();
        List<IdentityLink> identityLinks = repositoryService.getIdentityLinksForProcessDefinition(processDefinition.getId());
        for (IdentityLink link : identityLinks) {
            //此处是下一节点候选组，发送消息
            String groupId = link.getGroupId();

        }
    }




    /**
     * 参考：
     * 回退思路
     * 1.取得当前节点的信息
     * 2.取得当前节点的上一个节点的信息
     * 3.保存当前节点的流向
     * 4.新建流向，由当前节点指向上一个节点
     * 5。将当前节点的流向设置为上面新建的流向
     * 6.当前节点完成任务
     * 7.将当前节点的流向还原
     * 8.取得之前上个节点的执行人
     * 9.设置上个节点的assignee为之前的执行人
     * @param
     */
    public void backProcessToLast(Task task) {
        String processInstanceId = task.getProcessInstanceId();
        //  获取所有历史任务（按创建时间降序）
        List<HistoricTaskInstance> hisTaskList = historyService.createHistoricTaskInstanceQuery()
                .processInstanceId(processInstanceId)
                .orderByTaskCreateTime()
                .desc()
                .list();
        List<HistoricActivityInstance> hisActivityList = historyService.createHistoricActivityInstanceQuery()
                .processInstanceId(processInstanceId).list();
        if (CollectionUtils.isEmpty(hisTaskList) || hisTaskList.size() < 2) {
            return;
        }
        //  当前任务
        HistoricTaskInstance currentTask = hisTaskList.get(0);
        //  前一个任务
        HistoricTaskInstance lastTask = hisTaskList.get(1);
        //  当前活动
        HistoricActivityInstance currentActivity = hisActivityList.stream().filter(e -> currentTask.getId().equals(e.getTaskId())).collect(Collectors.toList()).get(0);
        //  前一个活动
        HistoricActivityInstance lastActivity = hisActivityList.stream().filter(e -> lastTask.getId().equals(e.getTaskId())).collect(Collectors.toList()).get(0);
        BpmnModel bpmnModel = repositoryService.getBpmnModel(task.getProcessDefinitionId());
        //  获取前一个活动节点
        FlowNode lastFlowNode = (FlowNode) bpmnModel.getMainProcess().getFlowElement(lastActivity.getActivityId());
        //  获取当前活动节点
        FlowNode currentFlowNode = (FlowNode) bpmnModel.getMainProcess().getFlowElement(currentActivity.getActivityId());

        //  临时保存当前活动的原始方向
        List<SequenceFlow> originalSequenceFlowList = new ArrayList<>();
        originalSequenceFlowList.addAll(currentFlowNode.getOutgoingFlows());
        //  清理活动方向
        currentFlowNode.getOutgoingFlows().clear();
        //  建立新方向
        SequenceFlow newSequenceFlow = new SequenceFlow();
        newSequenceFlow.setId("newSequenceFlowId");
        newSequenceFlow.setSourceFlowElement(currentFlowNode);
        newSequenceFlow.setTargetFlowElement(lastFlowNode);
        List<SequenceFlow> newSequenceFlowList = new ArrayList<>();
        newSequenceFlowList.add(newSequenceFlow);
        //  当前节点指向新的方向
        currentFlowNode.setOutgoingFlows(newSequenceFlowList);

        //  完成当前任务
        taskService.complete(task.getId());
        //  重新查询当前任务
        Task nextTask = taskService.createTaskQuery().processInstanceId(processInstanceId).singleResult();
        if (null != nextTask) {
            taskService.setAssignee(nextTask.getId(), lastTask.getAssignee());
        }
        //  恢复原始方向
        currentFlowNode.setOutgoingFlows(originalSequenceFlowList);
    }


    /**
     * 跳到最开始的任务节点（直接打回）
     * @param task 当前任务
     */
    public void backProcessToStart(Task task) {
        String processInstanceId = task.getProcessInstanceId();
        //  获取所有历史任务（按创建时间升序）
        List<HistoricTaskInstance> hisTaskList = historyService.createHistoricTaskInstanceQuery().processInstanceId(processInstanceId).orderByTaskCreateTime().asc().list();
        if (CollectionUtils.isEmpty(hisTaskList) || hisTaskList.size() < 2) {
            return;
        }
        //第一个任务
        HistoricTaskInstance startTask = hisTaskList.get(0);
        //当前任务
        HistoricTaskInstance currentTask = hisTaskList.get(hisTaskList.size() - 1);
        BpmnModel bpmnModel = repositoryService.getBpmnModel(task.getProcessDefinitionId());
        //获取第一个活动节点
        FlowNode startFlowNode = (FlowNode) bpmnModel.getMainProcess().getFlowElement(startTask.getTaskDefinitionKey());
        //获取当前活动节点
        FlowNode currentFlowNode = (FlowNode) bpmnModel.getMainProcess().getFlowElement(currentTask.getTaskDefinitionKey());
        //临时保存当前活动的原始方向
        List<SequenceFlow> originalSequenceFlowList = new ArrayList<>();
        originalSequenceFlowList.addAll(currentFlowNode.getOutgoingFlows());
        //清理活动方向
        currentFlowNode.getOutgoingFlows().clear();
        //建立新方向
        SequenceFlow newSequenceFlow = new SequenceFlow();
        newSequenceFlow.setId("newSequenceFlowId");
        newSequenceFlow.setSourceFlowElement(currentFlowNode);
        newSequenceFlow.setTargetFlowElement(startFlowNode);
        List<SequenceFlow> newSequenceFlowList = new ArrayList<>();
        newSequenceFlowList.add(newSequenceFlow);
        //当前节点指向新的方向
        currentFlowNode.setOutgoingFlows(newSequenceFlowList);
        //完成当前任务
        taskService.complete(task.getId());
        //重新查询当前任务
        Task nextTask = taskService.createTaskQuery().processInstanceId(processInstanceId).singleResult();
        if (null != nextTask) {
            List<IdentityLink> candidateGroups = taskService.getIdentityLinksForTask(startTask.getId());
            for (IdentityLink link : candidateGroups) {
                if (IdentityLinkType.CANDIDATE.equals(link.getType()) && link.getGroupId() != null) {
                    String groupId = link.getGroupId();
                    taskService.addCandidateGroup(nextTask.getId(), groupId);
                }
            }
        }
        //恢复原始方向
        currentFlowNode.setOutgoingFlows(originalSequenceFlowList);
    }


}
